home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Users Group Library 1996 July / C-C++ Users Group Library July 1996.iso / listings / v_13_08 / phillip2 / geosubs.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-02-21  |  12.5 KB  |  468 lines

  1.  
  2.     /***********************************************
  3.     *
  4.     *    file d:\cips\geosubs.c
  5.     *
  6.     *    Functions: This file contains
  7.     *       geometry
  8.     *       arotate
  9.     *       bilinear_interpolate
  10.     *
  11.     *    Purpose:
  12.     *       These functions performs different
  13.     *       geometric operations.
  14.     *
  15.     *    External Calls:
  16.     *       wtiff.c - round_off_image_size
  17.     *                 create_file_if_needed
  18.     *                 write_array_into_tiff_image
  19.     *       tiff.c - read_tiff_header
  20.     *       rtiff.c - read_tiff_image
  21.     *
  22.     *    Modifications:
  23.     *       20 October 1993- created
  24.     *
  25.     *************************************************/
  26.  
  27. #include "cips.h"
  28.  
  29. #define FILL 150
  30.  
  31.  
  32.  
  33.  
  34.  
  35.      /*******************************************
  36.      *
  37.      *   geometry(..
  38.      *
  39.      *   This routine performs geometric
  40.      *   transformations on the pixels in an
  41.      *   image array.  It performs basic
  42.      *   displacement, stretching, and rotation.
  43.      *
  44.      *   The basic equations are:
  45.      *
  46.      *   new x = x.cos(a) + y.sin(a) + x_displace
  47.      *           + x.x_stretch +x.y.x_cross
  48.      *
  49.      *   new y = y.cos(a) - x.sin(a) + y_displace
  50.      *           + y.y_stretch +x.y.y_cross
  51.      *
  52.      *******************************************/
  53.  
  54. geometry(in_name, out_name, the_image, out_image,
  55.         il, ie, ll, le, x_angle,
  56.         x_stretch, y_stretch,
  57.         x_displace, y_displace,
  58.         x_cross, y_cross,
  59.         bilinear)
  60.  
  61.    char   in_name[], out_name[];
  62.    float  x_angle, x_stretch, y_stretch,
  63.           x_cross, y_cross;
  64.    int    bilinear, il, ie, ll, le;
  65.    short  the_image[ROWS][COLS],
  66.           out_image[ROWS][COLS],
  67.           x_displace, y_displace;
  68. {
  69.    double cosa, sina, radian_angle, tmpx, tmpy;
  70.    float  fi, fj, x_div, y_div, x_num, y_num;
  71.    int    i, j, new_i, new_j;
  72.    struct tiff_header_struct image_header;
  73.  
  74.    create_file_if_needed(in_name, out_name, out_image);
  75.  
  76.    read_tiff_image(in_name, the_image, il, ie, ll, le);
  77.  
  78.       /******************************
  79.       *
  80.       *   Load the terms array with
  81.       *   the correct parameters.
  82.       *
  83.       *******************************/
  84.  
  85.       /* the following magic number is from
  86.          180 degrees divided by pi */
  87.    radian_angle = x_angle/57.29577951;
  88.    cosa  = cos(radian_angle);
  89.    sina  = sin(radian_angle);
  90.  
  91.       /************************************
  92.       *
  93.       *   NOTE: You divide by the
  94.       *   stretching factors. Therefore, if
  95.       *   they are zero, you divide by 1.
  96.       *   You do this with the x_div y_div
  97.       *   variables. You also need a
  98.       *   numerator term to create a zero
  99.       *   product.  You do this with the
  100.       *   x_num and y_num variables.
  101.       *
  102.       *************************************/
  103.  
  104.    if(x_stretch < 0.00001){
  105.       x_div = 1.0;
  106.       x_num = 0.0;
  107.    }
  108.    else{
  109.       x_div = x_stretch;
  110.       x_num = 1.0;
  111.    }
  112.  
  113.    if(y_stretch < 0.00001){
  114.       y_div = 1.0;
  115.       y_num = 0.0;
  116.    }
  117.    else{
  118.       y_div = y_stretch;
  119.       y_num = 1.0;
  120.    }
  121.  
  122.       /**************************
  123.       *
  124.       *   Loop over image array
  125.       *
  126.       **************************/
  127.  
  128.    printf("\n");
  129.    for(i=0; i<ROWS; i++){
  130.       if( (i%10) == 0) printf("%d ", i);
  131.       for(j=0; j<COLS; j++){
  132.  
  133.          fi = i;
  134.          fj = j;
  135.  
  136.          tmpx = (double)(j)*cosa         +
  137.                 (double)(i)*sina         +
  138.                 (double)(x_displace)     +
  139.                 (double)(x_num*fj/x_div) +
  140.                 (double)(x_cross*i*j);
  141.  
  142.          tmpy = (double)(i)*cosa         -
  143.                 (double)(j)*sina         +
  144.                 (double)(y_displace)     +
  145.                 (double)(y_num*fi/y_div) +
  146.                 (double)(y_cross*i*j);
  147.  
  148.          if(x_stretch != 0.0)
  149.             tmpx = tmpx - (double)(fj*cosa + fi*sina);
  150.          if(y_stretch != 0.0)
  151.             tmpy = tmpy - (double)(fi*cosa - fj*sina);
  152.  
  153.          new_j = tmpx;
  154.          new_i = tmpy;
  155.  
  156.          if(bilinear == 0){
  157.             if(new_j < 0       ||
  158.                new_j >= COLS   ||
  159.                new_i < 0       ||
  160.                new_i >= ROWS)
  161.                out_image[i][j] = FILL;
  162.             else
  163.                out_image[i][j] =
  164.                 the_image[new_i][new_j];
  165.          }  /* ends if bilinear */
  166.          else{
  167.             out_image[i][j] = 
  168.                bilinear_interpolate(the_image,
  169.                                     tmpx, tmpy);
  170.          }  /* ends bilinear if */
  171.  
  172.       }  /* ends loop over j */
  173.    }  /* ends loop over i */
  174.  
  175.    write_array_into_tiff_image(out_name, out_image,
  176.                                il, ie, ll, le);
  177.  
  178. }  /* ends geometry */
  179.  
  180.  
  181.  
  182.  
  183.      /*******************************************
  184.      *
  185.      *   arotate(..
  186.      *
  187.      *   This routine performs rotation about
  188.      *   any point m,n.
  189.      *
  190.      *   The basic equations are:
  191.      *
  192.      *   new x = x.cos(a) - y.sin(a)
  193.      *           -m.cos(a) + m + n.sin(a)
  194.      *
  195.      *   new y = y.cos(a) + x.sin(a)
  196.      *           -m.sin(a) - n.cos(a) + n
  197.      *
  198.      *******************************************/
  199.  
  200. arotate(in_name, out_name, the_image, out_image,
  201.         il, ie, ll, le, angle,
  202.         m, n, bilinear)
  203.    char   in_name[], out_name[];
  204.    float  angle;
  205.    int    bilinear, il, ie, ll, le;
  206.    short  the_image[ROWS][COLS],
  207.           out_image[ROWS][COLS],
  208.           m, n;
  209. {
  210.    double cosa, sina, radian_angle, tmpx, tmpy;
  211.    int    i, j, new_i, new_j;
  212.    struct tiff_header_struct image_header;
  213.  
  214.    create_file_if_needed(in_name, out_name, out_image);
  215.  
  216.    read_tiff_image(in_name, the_image, il, ie, ll, le);
  217.  
  218.  
  219.       /* the following magic number is from
  220.          180 degrees divided by pi */
  221.    radian_angle = angle/57.29577951;
  222.    cosa  = cos(radian_angle);
  223.    sina  = sin(radian_angle);
  224.  
  225.       /**************************
  226.       *
  227.       *   Loop over image array
  228.       *
  229.       **************************/
  230.  
  231.    printf("\n");
  232.    for(i=0; i<ROWS; i++){
  233.       if( (i%10) == 0) printf("%d ", i);
  234.       for(j=0; j<COLS; j++){
  235.  
  236.      /******************************************
  237.      *
  238.      *   new x = x.cos(a) - y.sin(a)
  239.      *           -m.cos(a) + m + n.sin(a)
  240.      *
  241.      *   new y = y.cos(a) + x.sin(a)
  242.      *           -m.sin(a) - n.cos(a) + n
  243.      *
  244.      *******************************************/
  245.  
  246.          tmpx = (double)(j)*cosa    -
  247.                 (double)(i)*sina    -
  248.                 (double)(m)*cosa    +
  249.                 (double)(m)         +
  250.                 (double)(n)*sina;
  251.  
  252.          tmpy = (double)(i)*cosa    +
  253.                 (double)(j)*sina    -
  254.                 (double)(m)*sina    -
  255.                 (double)(n)*cosa    +
  256.                 (double)(n);
  257.  
  258.          new_j = tmpx;
  259.          new_i = tmpy;
  260.  
  261.          if(bilinear == 0){
  262.             if(new_j < 0       ||
  263.                new_j >= COLS   ||
  264.                new_i < 0       ||
  265.                new_i >= ROWS)
  266.                out_image[i][j] = FILL;
  267.             else
  268.                out_image[i][j] =
  269.                 the_image[new_i][new_j];
  270.          }  /* ends if bilinear */
  271.          else{
  272.             out_image[i][j] = 
  273.                bilinear_interpolate(the_image,
  274.                                     tmpx, tmpy);
  275.          }  /* ends bilinear if */
  276.  
  277.       }  /* ends loop over j */
  278.    }  /* ends loop over i */
  279.  
  280.    write_array_into_tiff_image(out_name, out_image,
  281.                                il, ie, ll, le);
  282.  
  283. }  /* ends arotate */
  284.  
  285.  
  286.  
  287.  
  288.  
  289.      /*******************************************
  290.      *
  291.      *   bilinear_interpolate(..
  292.      *
  293.      *   This routine performs bi-linear
  294.      *   interpolation.
  295.      *
  296.      *   If x or y is out of range, i.e. less
  297.      *   than zero or greater than ROWS or COLS,
  298.      *   this routine returns a zero.
  299.      *
  300.      *   If x and y are both in range, this
  301.      *   routine interpolates in the horizontal
  302.      *   and vertical directions and returns
  303.      *   the proper gray level.
  304.      *
  305.      *******************************************/
  306.  
  307. bilinear_interpolate(the_image, x, y)
  308.    double x, y;
  309.    short  the_image[ROWS][COLS];
  310. {
  311.    double fraction_x, fraction_y,
  312.           one_minus_x, one_minus_y,
  313.           tmp_double;
  314.    int    ceil_x, ceil_y, floor_x, floor_y;
  315.    short  p1, p2, p3, result = FILL;
  316.  
  317.       /******************************
  318.       *
  319.       *   If x or y is out of range,
  320.       *   return a FILL.
  321.       *
  322.       *******************************/
  323.  
  324.    if(x < 0.0               ||
  325.       x >= (double)(COLS)   ||
  326.       y < 0.0               ||
  327.       y >= (double)(ROWS))
  328.       return(result);
  329.  
  330.    tmp_double = floor(x);
  331.    floor_x    = tmp_double;
  332.    tmp_double = floor(y);
  333.    floor_y    = tmp_double;
  334.    tmp_double = ceil(x);
  335.    ceil_x     = tmp_double;
  336.    tmp_double = ceil(y);
  337.    ceil_y     = tmp_double;
  338.  
  339.    fraction_x = x - floor(x);
  340.    fraction_y = y - floor(y);
  341.  
  342.    one_minus_x = 1.0 - fraction_x;
  343.    one_minus_y = 1.0 - fraction_y;
  344.  
  345.    tmp_double = one_minus_x * 
  346.                 (double)(the_image[floor_y][floor_x]) +
  347.                 fraction_x * 
  348.                 (double)(the_image[floor_y][ceil_x]);
  349.    p1         = tmp_double;
  350.  
  351.    tmp_double = one_minus_x * 
  352.                 (double)(the_image[ceil_y][floor_x]) +
  353.                 fraction_x * 
  354.                 (double)(the_image[ceil_y][ceil_x]);
  355.    p2         = tmp_double;
  356.  
  357.    tmp_double = one_minus_y * (double)(p1) +
  358.                 fraction_y * (double)(p2);
  359.    p3         = tmp_double;
  360.  
  361.  
  362.    return(p3);
  363.  
  364. }  /* ends bilinear_interpolate */
  365.  
  366.  
  367.  
  368.  
  369.      /*******************************************
  370.      *
  371.      *   get_geometry_options(..
  372.      *
  373.      *   This routine interacts with the user
  374.      *   to obtain the parameters to call the
  375.      *   geometry operations subroutines.
  376.      *
  377.      *******************************************/
  378.  
  379. get_geometry_options(operation, angle, 
  380.                      x_displace, y_displace, 
  381.                      x_stretch, y_stretch, 
  382.                      x_cross,  y_cross, 
  383.                      bilinear, m, n)
  384.    char  operation[];
  385.    int   *bilinear;
  386.    short *m, *n, *x_displace, *y_displace;
  387.    float *angle,
  388.          *x_cross, *y_cross, 
  389.          *x_stretch, *y_stretch;
  390. {
  391.    int not_finished, response;
  392.    not_finished = 1;
  393.    while(not_finished){
  394.  
  395.       printf("\nThe geomety options are:");
  396.       printf("\n\t1. Operation is %s", operation);
  397.       printf("\n\t2. Angle is %f", *angle);
  398.       printf("\n\t3. x-displace=%d y-displace=%d",
  399.          *x_displace, *y_displace);
  400.       printf("\n\t4. x-stretch=%f y-stretch=%f",
  401.          *x_stretch, *y_stretch);
  402.       printf("\n\t5. x-cross=%f y-cross=%f",
  403.          *x_cross, *y_cross);
  404.       printf("\n\t6. bilinear = %d", *bilinear);
  405.       printf("\n\t7. rotation points m=%d n=%d",
  406.          *m, *n);
  407.       printf("\n\nExamples:");
  408.       printf("\ngeometry needs: angle");
  409.       printf(" x-displace y-displace");
  410.       printf(" x-stretch y-stretch");
  411.       printf("\n                x-cross y-cross");
  412.       printf(" bilinear (1 or 0)");
  413.       printf("\nrotate needs: angle m n");
  414.       printf(" bilinear (1 or 0)");
  415.       printf("\n\nEnter choice (0 = no change) _\b");
  416.       get_integer(&response);
  417.  
  418.       if(response == 0)
  419.          not_finished = 0;
  420.  
  421.       if(response == 1){
  422.          printf("\nEnter operation:");
  423.          gets(operation);
  424.       }  /* ends if 1 */
  425.  
  426.       if(response == 2){
  427.          printf("\nEnter angle: ___\b\b\b");
  428.          get_float(angle);
  429.       }  /* ends if 2 */
  430.  
  431.       if(response == 3){
  432.          printf("\nEnter x-displace: ___\b\b\b");
  433.          get_integer(x_displace);
  434.          printf("\nEnter y-displace: ___\b\b\b");
  435.          get_integer(y_displace);
  436.       }  /* ends if 3 */
  437.  
  438.       if(response == 4){
  439.          printf("\nEnter x-stretch: ___\b\b\b");
  440.          get_float(x_stretch);
  441.          printf("\nEnter y-stretch: ___\b\b\b");
  442.          get_float(y_stretch);
  443.       }  /* ends if 4 */
  444.  
  445.       if(response == 5){
  446.          printf("\nEnter x-cross: ___\b\b\b");
  447.          get_float(x_cross);
  448.          printf("\nEnter y-cross: ___\b\b\b");
  449.          get_float(y_cross);
  450.       }  /* ends if 5 */
  451.  
  452.       if(response == 6){
  453.          printf("\nEnter bilinear: _\b");
  454.          get_integer(bilinear);
  455.       }  /* ends if 6 */
  456.  
  457.       if(response == 7){
  458.          printf("\nEnter rotation point m: _\b");
  459.          get_integer(m);
  460.          printf("\nEnter rotation point n: _\b");
  461.          get_integer(n);
  462.       }  /* ends if 7 */
  463.  
  464.  
  465.    }  /* ends while not_finished */
  466.  
  467. }  /* ends get_geometry_options */
  468.